<script lang="ts" setup name="ApprovalDetail">
import { nextTick, ref } from 'vue'
import { CloseBold, Link, Printer, Select } from '@element-plus/icons-vue'
import type { UploadInstance } from 'element-plus'
import { IKApprovalProcessDetail } from 'iking-web-ui'
import { _ } from 'iking-utils'
import type { approvalEndorseForm, recordsState } from './interface'
import { EFlowFormType } from './enum'
import { EFiledMap, ENodeType, EStatus } from './dict'
import ApprovalEndorse from './ApprovalEndorse.vue'
import PrintView from './PrintView.vue'
import { approvalApi } from '@/MainApp/apis/approval'
import { systemConfig } from '@/system.config'

const props = defineProps({
  visible: {
    type: Boolean,
    default: false
  },
  title: {
    type: String,
    default: () => '审批详情'
  },
  // 行数据
  rowData: {
    type: Object,
    default: null
  }
})

const emits = defineEmits<{
  (e: 'cancel', bool: boolean): void
  (e: 'handleConfirm'): void
}>()

enum EApproveType {
  加签 = 'endorse',
  退回 = 'sendBack',
  拒绝 = 'reject',
  同意 = 'agree'
}

const { dialog } = useConfig()
let MicroFormCom: any = null
try {
  const moudle: any = import.meta.glob('@/MicroApp/**/*.vue')

  if (systemConfig.arrpove?.componentPath)
    MicroFormCom = defineAsyncComponent(moudle[`@/MicroApp/${systemConfig.arrpove?.componentPath}`])
}
catch (error) {

}

const { uploadUrl, loadUrl, baseUrl } = useHttpUrl()
const approveFlowStore = useApproveFlowStore()
const { msgError, msgSuccess, msgBoxWarning } = useMessage()
const dVisible = ref(props.visible)
const loading = ref(false)
const approvalVisible = ref(false)
const detailData = ref<any>(null)
const detailVFormRef = ref()
const isCustomApproveDetail = computed(
  () => {
    const result = systemConfig.arrpove?.componentPath
    && detailData.value?.formType === EFlowFormType.已有表单
    && detailData.value?.viewProperty === null
    console.log('isCustomApproveDetail ', result)
    return result
  }

)
const isResubmit = ref(false)
const state = ref({
  data: [],
  returnNode: [],
  downloadUrl: loadUrl
})
const recordsData = ref<Array<recordsState>>([])
const approvalType = ref('passTo')
const formInstance: Ref<any> = ref<approvalEndorseForm>({
  approveComment: '',
  attachments: []
})
const instanceUserType = ref('')
const { lenContent } = useLength()
const activeName: Ref<any> | undefined = inject('activeName')

// 使用当前登录用户信息
const { user } = useConfig()

console.log('useCondfig user ', user)

const activeNames = computed(() => {
  // 没有从外部注入 activeName 时，则通过详情信息判断 activeName
  if (!activeName) {
    const groups = []
    // 我审批的
    const isApprover = (detailData.value?.currentInstanceUsers.map((item: any) => item.userId).includes(user.id)) ?? false
    if (isApprover)
      groups.push('IApproved')

    // 我提交的
    const isSubmitted = (detailData.value?.initiatorId === user.id) ?? false
    if (isSubmitted)
      groups.push('ISubmitted')

    return groups
  }
  return [activeName.value]
})
const processStatusMsg = ref('')

const handleClose = () => {
  emits('cancel', false)
  approveFlowStore.setSocketInfo({})
  dVisible.value = false
}
const formatUrl = (str: any) => {
  let url = ''
  if (str.includes('http') || str.includes('https'))
    url = str
  else url = state.value.downloadUrl + str

  return url
}
const setProcessNode = (dataList: any) => {
  const listData = {
    data: [],
    returnNode: [],
    downloadUrl: loadUrl
  }
  if (!dataList?.instanceNodes)
    dataList.instanceNodes = []

  if (!dataList?.recordNodes)
    dataList.recordNodes = []
  for (const item of dataList?.recordNodes) {
    item.lineType = 'solid'
    item.username = (item.executorUsers && item.executorUsers[0]?.userName) || ''
  }
  dataList?.instanceNodes?.forEach((element: any, index: any) => {
    element.lineType = 'dashed'
    element.sortOrder = dataList?.recordNodes.length + index + 1
    element.username
      = (element.executorUsers && element.executorUsers[0]?.userName) || ''
    if (index < 1)
      element.status = EStatus.等待
      // element.statusName = '审批中'
  })

  listData.data = [...dataList?.recordNodes, ...dataList?.instanceNodes] as any
  listData.data = listData.data?.sort(
    (a: any, b: any) => a.sortOrder - b.sortOrder
  )

  listData?.data?.map((item: any) => {
    if (item.backToRecordNodeId) {
      // 计算退回节点下标
      const obj: any = listData?.data?.find(
        (it: any) => it.id === item.backToRecordNodeId
      )
      item.returnNodeName = obj.name
      const arr = [obj.sortOrder, item.sortOrder]
      ;(listData.returnNode as any).push(arr)
    }
    if (item.type === ENodeType.抄送节点) {
      // 计算抄送时，已读未读情况
      const readList = item.executorUsers.filter((it: any) => {
        return it.accomplish
      })
      item.read = readList.length
      item.allRead = readList.length === item.executorUsers.length
    }
    // 图片附件列表
    item.attachments = item?.attachments?.map((it: any) => {
      return {
        ...it,
        id: it.id,
        originName: it.attachmentName,
        url: formatUrl(it.attachmentId),
        suffix: it.attachmentSuffix,
        size: Number(it.attachmentSize)
      }
    })
    item.attachment = item?.attachments?.[0] || null
    item.attachmentImg = item?.images?.map((it: any) => {
      return formatUrl(it)
    })
    return {
      ...item
    }
  })
  return listData
}
const getDetailData = async (v: any) => {
  recordsData.value = []
  state.value.data = []
  const { success, data } = await approvalApi.getDetailData(v.id)
  if (success) {
    detailData.value = data
    isResubmit.value
      = data.processInstance?.instanceNodes?.[0]?.type === 'INITIATOR'
      || data.processStatus === EStatus.同意

    instanceUserType.value
      = data.processInstance?.instanceNodes?.[0].multiExecutorType || ''
    if (data?.processInstance)
      state.value = _.cloneDeep(setProcessNode(data.processInstance))
    if (data?.processRecords?.length > 0) {
      data?.processRecords.forEach((item: any) => {
        const list = _.cloneDeep(setProcessNode(item))
        recordsData.value = [
          ...recordsData.value,
          ...[
            {
              ...list
            }
          ]
        ]
      })
    }

    if (data?.processStatus === 'APPROVING') {
      const userLength = detailData.value?.currentInstanceUsers?.length
      processStatusMsg.value
        = userLength > 1
          ? `等待${data?.currentInstanceUsers?.[0]?.userName}等${userLength}人审批`
          : `等待${data?.currentInstanceUsers?.[0]?.userName}审批`
    }
    else {
      processStatusMsg.value = data?.processStatusName
    }
    // if (detailData.value.formType === EFlowFormType.已有表单)
    //   return
    const json = JSON.parse(data?.viewProperty || '')
    const formData = JSON.parse(data?.formData || '{}')

    nextTick(() => {
      console.log('detailVFormRef.value ', detailVFormRef.value)
      detailVFormRef.value?.setFormJson(json)
      detailVFormRef.value?.setFormData(formData)
    })
  }
}

watch(
  () => props.visible,
  async (visible: any) => {
    dVisible.value = visible
    if (!visible) {
      state.value = {
        data: [],
        returnNode: [],
        downloadUrl: loadUrl
      }
      recordsData.value = []
      loading.value = false
      return
    }
    getDetailData(props.rowData)
  }
)

watch(() => activeNames?.value, (nval: any) => {
  console.log('activeNames nval change', nval)
},
{ deep: true }
)

// watch(
//   () => props.rowData,
//   (v: any) => {
//     if (v)
//       getDetailData(v)
//   },
//   { deep: true }
// )

const handleApproval = (type: string) => {
  approvalType.value = type
  if (type === EApproveType.退回) {
    const backToInitiator = detailData.value?.processInstance?.instanceNodes?.[0].backToInitiator || false
    if (backToInitiator) {
      msgBoxWarning('确认提示', '确认后此审批单将被直接退回至发起人', () => {
        handleEndorseConfirm(null)
      })
      return
    }
  }
  approvalVisible.value = true
}
const handleEndorse = () => {
  approvalVisible.value = false
}

const handleEndorseConfirm = async (value: any) => {
  loading.value = true
  let res: any
  const images
    = value?.images?.map((item: any) => {
      return item.response.data.url
    }) || []
  const attachments
    = value?.attachments?.map((item: any) => {
      return {
        attachmentId: item?.attachmentId,
        attachmentName: item?.attachmentName,
        attachmentSuffix: item?.attachmentSuffix,
        attachmentSize: item?.attachmentSize
      }
    }) || []
  const formData = JSON.stringify(detailVFormRef?.value?.formDataModel)
  const appendExecutorUserIds
    = value?.appendExecutorUserIds?.map((item: any) => {
      return item.elementId
    }) || []

  let params = {
    ...value,
    formInstanceId: props.rowData?.id,
    images,
    attachments,
    appendExecutorUserIds,
    formData
  }
  if (approvalType.value === 'sendBack') {
    params = {
      ...params,
      appendExecutorUserIds: [],
      backToInstanceNodeUserIds: appendExecutorUserIds
    }
  }
  switch (approvalType.value) {
    case 'passTo':
      res = approvalApi.passApproval(params)
      break
    case EApproveType.加签:
      res = approvalApi.appendApproval(params)
      break
    case EApproveType.退回:
      res = approvalApi.backApproval(params)
      break
    case EApproveType.拒绝:
      res = approvalApi.rejectApproval(params)
      break
    case EApproveType.同意:
      res = approvalApi.passApproval(params)
      break
    default:
      break
  }
  res?.then((data: any) => {
    if (data?.success) {
      approvalVisible.value = false
      loading.value = false
      msgSuccess(data?.msg)
      getDetailData(props.rowData)
      // 同意或拒绝时
      if (
        [EApproveType.同意, EApproveType.拒绝].includes(
          approvalType.value as any
        )
      ) {
        dVisible.value = false
        emits('handleConfirm')
      }
    }
    else {
      loading.value = false
      msgError(data?.msg)
    }
  })
}
const sendComment = async () => {
  if (!formInstance.value.approveComment) {
    msgError('请添加评论')
    return
  }
  const attachments
    = formInstance.value.attachments?.map((item: any) => {
      return {
        attachmentId: item?.response?.data?.id,
        attachmentName: item?.response?.data?.originName,
        attachmentSuffix: item?.response?.data?.suffix,
        attachmentSize: item?.response?.data?.fileSize
      }
    }) || []
  const params = {
    ...formInstance.value,
    formInstanceId: props.rowData?.id,
    attachments
  }
  const { success, msg } = await approvalApi.commentApproval(params)
  if (success) {
    formInstance.value = {
      approveComment: '',
      attachments: []
    }
    state.value = {
      data: [],
      returnNode: [],
      downloadUrl: loadUrl
    }
    recordsData.value = []
    getDetailData(props.rowData)
    msgSuccess(msg)
  }
  else {
    msgError(msg)
  }
}
const handlePressTo = async () => {
  loading.value = true
  const params = {
    formInstanceId: props.rowData?.id
  }
  const { success, msg } = await approvalApi.remindApproval(params)
  if (success) {
    approvalVisible.value = false
    // dVisible.value = false
    loading.value = false
    msgSuccess(msg)
    emits('handleConfirm')
  }
  else {
    loading.value = false
    msgError(msg)
  }
}
const handleRevocation = async () => {
  loading.value = true
  msgBoxWarning('确定要撤销吗?', '请确定要撤销该审批申请', async () => {
    const params = {
      formInstanceId: props.rowData?.id
    }
    const { success, msg } = await approvalApi.revokeApproval(params)
    if (success) {
      approvalVisible.value = false
      // dVisible.value = false
      loading.value = false
      msgSuccess(msg)
      emits('handleConfirm')
    }
    else {
      loading.value = false
      msgError(msg)
    }
  })
}
const handleResubmit = async () => {
  loading.value = true
  const params = {
    formInstanceId: props.rowData?.id
  }
  const { success, msg } = await approvalApi.resubmitApproval(params)
  if (success) {
    approvalVisible.value = false
    // dVisible.value = false
    loading.value = false
    msgSuccess(msg)
    emits('handleConfirm')
  }
  else {
    loading.value = false
    msgError(msg)
  }
}

const isLoginSelf = computed(() => {
  return (
    detailData.value?.currentInstanceUsers?.findIndex((cur: any) => {
      return cur.userId === user?.id
    }) >= 0
  )
})

/**
 * 允许操作
 */
const allowOperation = computed(() => {
  // 当前流程状态为审批中时
  const case1 = ['WAIT_FOR_INITIATE', 'APPROVING'].includes((detailData.value?.processStatus))
  return case1
})

const isApproving = computed(() => {
  return detailData.value?.processStatus === 'APPROVING'
})

const isWaitForInitiate = computed(() => {
  return detailData.value?.processStatus === 'WAIT_FOR_INITIATE'
})

const isMineApprove = computed(() => {
  return activeNames?.value.includes('IApproved') && isLoginSelf.value
})

/** 打印 start */
const token = useToken()
const printState = reactive({
  visible: false,
  templateId: '',
  dataId: ''
})
const print = () => {
  printState.templateId = detailData.value?.reportTemplateId ?? ''
  printState.dataId = detailData.value?.id ?? ''
  printState.visible = true
}
/** 打印 end */

const uploadRef: Ref<null | UploadInstance> = ref(null)

const handCheckFile = () => {
  if (formInstance.value.attachments?.length)
    uploadRef?.value?.clearFiles()
}
</script>

<template>
  <el-dialog
    v-model="dVisible"
    :title="title"
    draggable
    :width="isCustomApproveDetail ? 'auto' : dialog.l"
    align-center
    :close-on-click-modal="false"
    append-to-body
    class="approval-detail-cen"
    @closed="handleClose"
  >
    <div class="detail-cen">
      <div class="detail-top">
        <div class="top-cen">
          <span> 审批编号：{{ detailData?.serialNo }} </span>
          <!-- <div v-if="false">
            <el-button
              :icon="Notification"
              text
              title="分享"
              class="more-icon"
            />
            <el-button :icon="Download" text title="下载" class="more-icon" />

            <el-button :icon="DocumentAdd" text title="再次提交" class="more-icon" />
          </div> -->
          <el-button
            :icon="Printer"
            text
            title="打印"
            class="more-icon"
            @click="print"
          />
        </div>
        <div class="top-cen">
          <p class="owne-cen">{{ detailData?.title }}</p>
        </div>
        <div class="top-cen">
          <div class="cen-dept">
            <IkSvgIcon
              :size="16"
              disabled
              name="iksvg_wenjianjia"
              class="mr-[8px]"
              :padding="0"
            />
            <span>所在部门：{{ detailData?.initiatorDeptName || '--' }}</span>
          </div>
          <span class="at-me">{{ processStatusMsg }}</span>
        </div>
      </div>
      <div class="detail-bg" :class="{ readonly: isCustomApproveDetail }">
        <MicroFormCom
          v-if="isCustomApproveDetail"
          :data="detailData"
          :is-edit="false"
        />
        <VFormRender v-else ref="detailVFormRef" />
      </div>
      <!-- <div class="detail-content" v-show="recordsData.length > 0">
        <IKApprovalProcessDetail
          :returnNode="recordsData[0]?.returnNode || []"
          :defaultStatus="EStatus"
          :defaultNodeType="ENodeType"
          :dataList="recordsData[0]?.data || []"
          :defaultFieldMap="EFiledMap"
        />
      </div> -->
      <div
        v-for="(item, index) in recordsData"
        :key="index"
        class="detail-content"
      >
        <IKApprovalProcessDetail
          :return-node="item.returnNode || []"
          :default-status="EStatus"
          :default-node-type="ENodeType"
          :data-list="item.data || []"
          :default-field-map="EFiledMap"
          :picker-url="`${baseUrl}/server/component/pick/mix`"
          :file-url="loadUrl"
        />
      </div>
      <div v-show="state.data.length > 0" class="detail-content">
        <IKApprovalProcessDetail
          :return-node="state.returnNode"
          :default-status="EStatus"
          :default-node-type="ENodeType"
          :data-list="state.data"
          :default-field-map="EFiledMap"
          :picker-url="`${baseUrl}/server/component/pick/mix`"
          :file-url="loadUrl"
        />
      </div>
      <div class="detail-content">
        <el-input
          v-model.trim="formInstance.approveComment"
          type="textarea"
          :maxlength="lenContent"
          placeholder="发布评论"
          :rows="5"
          show-word-limit
        />
        <div class="instance-comment">
          <!-- <IkUploadFile
            v-model="formInstance.attachments"
            tip
            action="http://127.0.0.1:4523/m1/687531-0-default/upload/file"
            tip-text="只允许上传.xls、.doc文件，单个文件大小不能超过5M"
            @success="handSuccess"
          /> -->
          <el-upload
            ref="uploadRef"
            v-model:file-list="formInstance.attachments"
            class="upload-demo"
            :action="uploadUrl"
            :limit="1"
            :auto-upload="true"
          >
            <template #trigger>
              <el-button :icon="Link" link @click="handCheckFile"> 上传文件 </el-button>
            </template>
          </el-upload>
          <el-button :loading="loading" link @click="sendComment">
            发送
          </el-button>
        </div>
      </div>
    </div>
    <template #footer>
      <!-- <el-button type="info" @click="handleApproval('passTo')" plain round>
        转交
      </el-button> -->
      <template v-if="allowOperation">
        <div class="flex" style="justify-content: flex-end;">
          <el-button
            v-if="(activeNames ?? '').includes('IApproved') && isApproving"
            type="info"
            plain
            round
            :loading="loading"
            @click="handleApproval(EApproveType.加签)"
          >
            加签
          </el-button>
          <el-button
            v-if="(activeNames ?? '').includes('IApproved') && isApproving"
            type="info"
            plain
            round
            :loading="loading"
            @click="handleApproval(EApproveType.退回)"
          >
            退回
          </el-button>
          <el-button
            v-if="(activeNames ?? '').includes('ISubmitted') && !isResubmit"
            type="info"
            plain
            round
            :loading="loading"
            @click="handlePressTo"
          >
            催办
          </el-button>
          <el-button
            v-if="(activeNames ?? '').includes('ISubmitted') && (isApproving || isWaitForInitiate)"
            type="info"
            plain
            round
            :loading="loading"
            @click="handleRevocation"
          >
            撤销
          </el-button>
          <el-button
            v-if="(activeNames ?? '').includes('ISubmitted') && isWaitForInitiate"
            type="info"
            plain
            round
            :loading="loading"
            @click="handleResubmit"
          >
            再次提交
          </el-button>
          <el-button-group v-if="isMineApprove && isApproving" class="ml-4 result-btn-group">
            <el-button
              type="primary"
              round
              plain
              :icon="CloseBold"
              :loading="loading"
              @click="handleApproval(EApproveType.拒绝)"
            >
              拒绝
            </el-button>
            <el-button
              type="primary"
              round
              :icon="Select"
              :loading="loading"
              @click="handleApproval(EApproveType.同意)"
            >
              同意
            </el-button>
          </el-button-group>
        </div>
      </template>
    </template>
  </el-dialog>
  <ApprovalEndorse
    :visible="approvalVisible"
    :approval-type="approvalType"
    :instance-user-type="instanceUserType"
    :row-data="$props.rowData"
    @update:visible="handleEndorse"
    @handleConfirm="handleEndorseConfirm"
  />

  <!-- src-prefix="http://192.168.2.45:6002" -->
  <PrintView
    v-model="printState.visible"
    :token="token"
    :template-id="printState.templateId"
    :data-id="printState.dataId"
  />
</template>

<style lang="scss">
.approval-detail-cen {
  min-width: 684px;

  .el-dialog__body {
    height: 75vh !important;
    padding: 0 !important;
    overflow: auto !important;
    flex: 1;
  }

  .detail-cen {
    background-color: var(--ik-border-color) !important;

    .detail-top {
      padding: 15px 24px;
      margin-bottom: 10px;
      background-color: var(--el-bg-color);

      .top-cen {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 6px 0;

        .owne-cen {
          font-size: 20px;
          font-weight: 650;
        }

        .cen-dept {
          font-size: 12px;
          display: flex;
        }

        .pen-btn {
          width: 20px;
          height: 20px;
          margin-right: 15px;
        }

        .at-me {
          font-size: 12px;
          color: rgb(245 154 35);
        }
      }

      .more-icon {
        font-size: 18px;
        height: 30px;
        border: none;
        width: 30px;
        cursor: pointer;
        margin-left: 8px;
        transition: all 0.25s;
        border-radius: 6px;
      }
    }

    .detail-bg {
      padding: 15px 24px;
      background-color: var(--el-bg-color);
      margin-bottom: 10px;
      position: relative;

      &:not(.readonly)::after {
        content: ' ';
        display: block;
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        height: 100%;
        z-index: 9;
      }
    }

    .detail-content {
      padding: 15px 24px;
      background-color: var(--el-bg-color);
      color: #999;
      margin-bottom: 10px;

      .instance-comment {
        display: flex;
        align-items: flex-start;
        justify-content: space-between;
        margin-top: 15px;
      }
    }
  }

  .el-dialog__footer {
    border-top: 1px solid var(--ik-border-color) !important;
    padding: 20px !important;

    button {
      width: 100px !important;
    }
  }
}

.result-btn-group{
  width: 206px;
}
</style>
